package breakthrough;

import java.util.ArrayList;

import breakthrough.XiBreakthroughPlayer.EvalVars;

import game.GameMove;
import game.GamePlayer;
import game.GameState;


//Plays defensively
public class MostSquaresOwnedBreakthroughPlayer extends GamePlayer{
	
	public final int MAX_SEARCH_DEPTH = 6;
	
	public MostSquaresOwnedBreakthroughPlayer(String nickname){
		
		//Is this deterministic?
		super(nickname, new BreakthroughState(), false);
	
	}
	
	public GameMove getMove(GameState state, String lastMv){
		
		return getBestMove((BreakthroughState)state);
		
	}
	
	/**
     * Returns the move considered best for the given state.
     * 
     * @param state
     *            the state to search from
     * @return the best move, ever
     */
    protected BreakthroughMove getBestMove(final BreakthroughState state)
    {    	
    	ArrayList<BreakthroughMove> moves = BreakthroughUtil.getLegalMoves(state);

        BreakthroughMove bestMove = moves.get(0);
        
        int bestScore = -Integer.MAX_VALUE;

        for (BreakthroughMove move : moves) {
        	
        	BreakthroughState successor = (BreakthroughState)state.clone();
            successor.makeMove(move);

            int score = alphaBeta(successor, MAX_SEARCH_DEPTH, -Integer.MAX_VALUE, Integer.MAX_VALUE);

            if (score > bestScore) {
                bestMove = move;
                bestScore = score;
            }
        }

        return bestMove;
    }
	
	public int alphaBeta(BreakthroughState state, int depth, int alpha, int beta){
		
		if(depth == MAX_SEARCH_DEPTH  || state.status != GameState.Status.GAME_ON)
			return evalState(state);
		
		ArrayList<BreakthroughMove> moves = BreakthroughUtil.getLegalMoves(state);
		
		int bestMoveScore = 0; // just a default to be changed in a sec
		
		//Max node
		if(state.who == this.side){
			
			bestMoveScore = -Integer.MAX_VALUE;
			
			for(BreakthroughMove move : moves){
				
				BreakthroughState successor = (BreakthroughState)state.clone();
	            successor.makeMove(move);
				
				int moveScore = alphaBeta(successor, depth + 1, alpha, beta);
				
				if(moveScore > bestMoveScore)
					bestMoveScore = moveScore;
				
				//prune case
				if(moveScore >= beta)
					return moveScore;
				else if(moveScore > alpha)
					alpha = moveScore;
				
			}
		}
		//Min node
		else{
			
			bestMoveScore = Integer.MAX_VALUE;
			
			for(BreakthroughMove move : moves){
				
				BreakthroughState successor = (BreakthroughState)state.clone();
	            successor.makeMove(move);
				
				int moveScore = alphaBeta(state, depth + 1, alpha, beta);
				
				if( moveScore < bestMoveScore)
					bestMoveScore = moveScore;
					
				//prune case
				if(moveScore <= alpha)
					return moveScore;
				else if(moveScore < beta)
					beta = moveScore;
				
			}
		}
		
		return bestMoveScore;
	}
	
	private int evalState(BreakthroughState state){
		
		//LONG TERM
		//A player owns every square on a file past the first uncontested
		//attackable or owned square.
		
		//NOW
		//Minimize pawn spread & maximize guarding
		
		//char mySym = (this.side == GameState.Who.HOME ? state.homeSym : state.awaySym);
		
		//for(int col = 0; col < state.board[0].length; col++){
			
		//	for(int row = 0; row < state.board.length; row++){
				
		//		if(state.board[row][col] == state.homeSym)
				
				
		//	}
			
		//}
		
		//EvalVars player = new EvalVars(state.getWho());
        //EvalVars opponent = new EvalVars(state.getWho() == GameState.Who.HOME ? GameState.Who.AWAY : GameState.Who.HOME);
		if (state.getStatus() != GameState.Status.GAME_ON) {
            if (thisPlayerIsWinner(state)) {
                return Integer.MAX_VALUE;
            }
            else {
                return -Integer.MAX_VALUE;
            }
        }

        char playerSym = (this.side == GameState.Who.HOME ? BreakthroughState.homeSym : BreakthroughState.awaySym);
        
        char opponentSym = (this.side == GameState.Who.HOME ? BreakthroughState.awaySym : BreakthroughState.homeSym);

        int playerPieces = 0;
        int opponentPieces = 0;
        
        for (int row = 0; row < BreakthroughState.N; ++row) {
            for (int col = 0; col < BreakthroughState.N; ++col) {
                if (state.board[row][col] == playerSym) {
                    ++playerPieces;
                }
                else if (state.board[row][col] == opponentSym) {
                    ++opponentPieces;
                }
            }
        }

        int score = 0;

        score += 1 * (playerPieces - opponentPieces);


        return score;
		
		
	}
	
    /**
     * Returns whether the game is over and this player has won.
     * 
     * @param state
     *            the state to be examined
     * @return true if the game is over and the player is the winner; false
     *         otherwise
     */
    protected final boolean thisPlayerIsWinner(final BreakthroughState state)
    {
        // smithre5: This is conceptually a bit overloaded. False doesn't say
        // that the player hasn't won, but that the game isn't over or that the
        // player hasn't won.

        boolean result = false;
        GameState.Status status = state.getStatus();

        if (GameState.Status.GAME_ON != status) {
            if (GameState.Status.HOME_WIN == status && GameState.Who.HOME == this.side) {
                result = true;
            }
            else if (GameState.Status.AWAY_WIN == status && GameState.Who.AWAY == this.side) {
                result = true;
            }
        }

        return result;
    }
    
    public GameState.Who getSide(){
    	return this.side;
    }
	
	/**
     * Runs the player.
     * 
     * @param args
     *            command-line arguments to the player
     */
    public static void main(String[] args)
    {
    	MostSquaresOwnedBreakthroughPlayer p = new MostSquaresOwnedBreakthroughPlayer("Mike");
        p.compete(args);
        
       // BreakthroughState state = new BreakthroughState();
       // state.who = p.getSide();
        //state.board[0][0] = 'B';
        
        //p.getMove(state, "");
        
    }
	
}
